package ee.ut.aa.neuraltic.logic;

import org.apache.log4j.Logger;

import ee.ut.aa.neuraltic.model.Board;

public class TicEvaluator implements BoardEvaluator {
	
	private static Logger log = Logger.getLogger(TicEvaluator.class);

	@Override
	public int findWinner( Board board ) {
		
		int[] fields = board.getFields();
		
		for( int i = 0; i < board.getSize(); i++ ) {
			
			if ( isWinningSpot( fields, i ) )
				return fields[i];
		}
		
		return 0;
	}

	@Override
	public boolean isGameOver( Board board ) {

		boolean result = false;
				
		int[] fields = board.getFields();
		
		log.debug( "Evaluating board." );
		
		if( board.getLegalMoves().size() == 0 )
			return true;

		for( int i = 0; i < fields.length; i++ ) {
			
			result = isWinningSpot(fields, i);
			
			if( result )
				return true;
		}
		
		log.debug( "Game is not over.. returning FALSE" );
		
		return false;
	}

	private boolean isWinningSpot( int[] fields, int index ) {
		
		int size = 9;
		int width = 3;
		
		int player = fields[index];
		
		if( player == 0 )
			return false;

		log.debug( "Checking if spot index=" + index + " is winning spot for player=" + player );
		
		boolean leToRi = leftToRight( fields, index, player, size, width );
		
		boolean toToBo = topToBottom( fields, index, player, size, width );

		boolean diagon = diagonal( fields, index, player, size, width );
		
		boolean diaRev = diagReverse( fields, index, player, size, width );
		
		if( leToRi || toToBo || diagon || diaRev )
			return true;

		log.debug( "Did not find any winning combination for player=" + player );
		
		return false;
	}
	
	private boolean leftToRight( int[] fields, int index, int player, int size, int width ) {
		
		int maxLength = 0;
		
		// Check left-to-right
		for( int i = index; i < index + 3 && i < size; i++ ) {
			
			if( fields[i] == player )
				maxLength++;
		}
		
		log.debug( "Max length on left-to-right= " + maxLength );
		
		// Check if was winning move
		// Check warping to next row as well
		if( maxLength >= 3 && width - ( index % width ) >= 3 )
			return true;
		else
			return false;
	}
	
	private boolean topToBottom( int[] fields, int index, int player, int size, int width ) {

		int maxLength = 0;	
		
		for( int i = index; i < index + 3 * width && i < size; i = i + width ) {
			if( fields[i] == player )
				maxLength++;
		}
		
		log.debug( "Max length on top-to-bottom= " + maxLength );
		
		// Check if was winning move
		// No warping to next row check needed here
		if( maxLength >= 3 )
			return true;

		return false;
	}
	
	//TODO: diagonal also backwards!
	private boolean diagonal( int[] fields, int index, int player, int size, int width ) {

		int maxLength = 0;
		
		for( int i = index; i < index + 3 * width + width && i < size; i = i + 1 + width ) {
			if( fields[i] == player )
				maxLength++;
			else
				break;
		}
		
		log.debug( "Max length on diagonal= " + maxLength );
		
		// Check if was winning move
		// Check warping to next row as well - same check as in left-to-right
		if( maxLength >= 3 && width - ( index % width ) >= 3 )
			return true;

		return false;
	}
	
	private boolean diagReverse( int[] fields, int index, int player, int size, int width ) {

		int maxLength = 0;
		
		for( int i = index; i < index + 3 * width + width && i < size; i = i - 1 + width ) {
			if( fields[i] == player )
				maxLength++;
			else
				break;
		}
		
		log.debug( "Max length on reverse diagonal= " + maxLength );
		
		// Check if was winning move
		// Check warping to next row as well - almost same check as in left-to-right
		if( maxLength >= 3 && index % width >= 3 - 1 )
			return true;

		return false;
	}
}
